package com.joinway.framework.extension.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.reflections.ReflectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.joinway.framework.extension.utils.data.Constructor;
import com.joinway.framework.extension.utils.data.StringConstructor;

/**
 * 数据处理共通方法
 * @author liliang
 *
 */
public final class DataUtils {
	
	private final static Logger log = LoggerFactory.getLogger(DataUtils.class);
	
	public static enum Sort{Asc, Desc};
	
	public static int getSize(Map<?, ?> map){
		return map == null ? 0 : map.size();
	}
	
	public static int getSize(Collection<?> c){
		return c == null ? 0 : c.size();
	}

	/**
	 * 将任意对象转化为int类型
	 * @param obj 要转换的对象 
	 * @return 转换后的int值
	 * @see com.joinway.framework.extension.utils.NumberUtils
	 * @deprecated 使用<code>NumberUtils.convertToInt(obj)</code>代替
	 */
	@Deprecated public static int convertToInt(Object obj){
		return NumberUtils.convertToInt(obj);
		
	}
	
	/**
	 * 将任意对象转换为布尔型
	 * <ul>
	 * <li>如果对象是布尔型，则返回输入参数值</li>
	 * <li>如果对象是数值型，值等于于0为false,其它为true</li>
	 * <li>如果对象是字符型，去掉空格后长度大于0则为true，反之false</li>
	 * <li>其它对象，不为空时转化为true，否则false</li>
	 * </ul>
	 * @param obj 要转换的目标对象
	 * @return 转换后的布尔型
	 */
	public static boolean convertBool(Object obj){
		boolean ret = false;
		
		if(obj instanceof Boolean){
			ret = (Boolean)obj;
		}else if(obj instanceof Number){
			ret = new BigDecimal(String.valueOf(obj)).compareTo(BigDecimal.ZERO) != 0;
		}else if(obj instanceof String){
			ret = String.valueOf(obj).trim().length() > 0; 
		}else{
			ret = obj != null;
		}
		
		return ret;
	}

	/**
	 * 将将任意对象转换为字符串
	 * <ul>
	 * <li>如果对象是字符串，返回去除首尾空格的字符串</li>
	 * <li>如果对象是null，返回空串</li>
	 * <li>其它对象，调用<code>toString()</code>方法后去除首尾空格</li>
	 * </ul>
	 * @param obj 要转换的目标对象
	 * @return 转换后的字符串
	 */
	public static String convertToString(Object obj){
		String value = "";
		
		if(obj != null){
			value = StringUtils.trimToEmpty(obj.toString());
		}
			
		return value;
	}
	
//	/**
//	 * 将将任意对象转换为字符串
//	 * @param obj
//	 * @return
//	 */
//	public static String convertToEmptyString(Object obj){
//		String value = "";
//		
//		if(obj != null){
//			value = StringUtils.trimToEmpty(obj.toString());
//		}
//			
//		return value;
//	}
	
//	/**
//	 * 将将任意对象转换为null
//	 * @param obj
//	 * @return
//	 */
//	public static String convertToNullString(Object obj){
//		String value = null;
//		
//		if(obj != null){
//			value = StringUtils.trimToNull(obj.toString());
//		}
//			
//		return value;
//	}
	
	/**
	 * 把集合中内容的按拼音字母升序排序
	 * @param list 属性中包含汉字的对象
	 * @param picker 获取包含汉字属性的值
	 */
	public static<T> void sortByPinYin(List<T> list, ChineseFieldPicker<T> picker){
		sortByPinYin(list, true, picker);
	}
	
	/**
	 * 把集合中内容的按拼音字母排序
	 * @param list 属性中包含汉字的对象
	 * @param asc true为升序，反之倒序
	 * @param picker 获取包含汉字属性的值
	 */
	@SuppressWarnings("rawtypes")
	public static<T> void sortByPinYin(List<T> list, final boolean asc, final ChineseFieldPicker<T> picker){
		final Comparator comparator = Collator.getInstance(java.util.Locale.CHINA);
		Collections.sort(list, new Comparator<T>(){
			@SuppressWarnings("unchecked")
			@Override
			public int compare(T t1, T t2) {
				int ret = 0;
				if(asc){
					ret = comparator.compare(picker.getChineseField(t1), picker.getChineseField(t2));
				}else{
					ret = comparator.compare(picker.getChineseField(t2), picker.getChineseField(t1));
				}
				return ret;
			}
		});
	}
	
//	@Deprecated
//	public static String plainToString(Collection<?> c, String field) throws Exception {
//		return plainToString(c, field, ",");
//	}
	
//	@Deprecated
//	public static String plainToString(Collection<?> c, String field, String separator) throws Exception {
//		String plain = "";
//		
//		if(CollectionUtils.isNotEmpty(c)){
//			for(Object o : c){
//				Object e = PropertyUtils.getProperty(o, field);
//				plain += convertToString(e) + separator;
//			}
//			
//			plain = plain.substring(0, plain.length() - 1);
//		}
//		
//		return plain;
//	}
	
	@Deprecated
	public static boolean isJsonData(String text){
		String value = StringUtils.trimToEmpty(text).replaceAll("\\s+", "");
		return value.startsWith("{") && value.endsWith("}") || value.startsWith("[{") && value.endsWith("}]");
	}
	
	/**
	 * 把source集合加到target中，如果source为空，则忽略
	 * @param target 目标对象
	 * @param source 源对象
	 */
	@SuppressWarnings("unchecked")
	public static void addAllIgnoreEmpty(Collection<?> target, Collection<?> source){
		if(CollectionUtils.isNotEmpty(source)){
			((Collection<Object>)target).addAll(source);
		}
	}
	
	/**
	 * 把ISO-8859-1字符串转化成UTF8格式
	 * @param text ISO-8859-1编码字符串
	 * @return UTF8编码字符串
	 * @throws Exception
	 */
	public static String convertTextToUtf8(String text) throws Exception {
		return new String(text.getBytes("ISO-8859-1"), "UTF-8");
	}

	/**
	 * 获得对象中除<code>static,transient,final</code>修饰的所有成员变量
	 * @param type 要查看的类
	 * @return 成员变量列表
	 */
	public static List<Field> getValidFields(Class<?> type){
		List<Field> validFields = new LinkedList<>();
		
		@SuppressWarnings("unchecked")
		Set<Field> fields = ReflectionUtils.getAllFields(type);
		
		if(getSize(fields) > 0){
			for(Field field : fields){
				int modifiers = field.getModifiers();
				if(!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers) && !Modifier.isFinal(modifiers)){
					validFields.add(field);
				}
			}
		}
		
		return validFields;
	}
	
    /**
     * 把html中的<code>&lt;,&gt;,&amp;,&quot;</code>转义
     * @param message 要过滤的html字符串
     * @return 过滤后的字符串
     */
	public static String filterHtml(String message){
		
        if (message == null)
            return "";

        char content[] = new char[message.length()];
        message.getChars(0, message.length(), content, 0);
        StringBuilder result = new StringBuilder(content.length + 50);
        for (int i = 0; i < content.length; i++) {
            switch (content[i]) {
            case '<':
                result.append("&lt;");
                break;
            case '>':
                result.append("&gt;");
                break;
            case '&':
                result.append("&amp;");
                break;
            case '"':
                result.append("&quot;");
                break;
            default:
                result.append(content[i]);
            }
        }
        return (result.toString());

	}
	
//	/**
//	 *  
//	 * @param list
//	 * @return
//	 */
//	public static<T extends Cloneable> List<T> clone(List<T> list){
//		List<T> objects = new ArrayList<>();
//		
//		if(CollectionUtils.isNotEmpty(list)){
//			for(T t : list){
//				objects.add(ObjectUtils.clone(t));
//			}
//		}
//		
//		return objects;
//	}
	
	/**
	 * 获得数组中第一个不是空字符串的值
	 * @param values 目标数组
	 * @return 第一个非空数值
	 */
	public static String getFirstNonEmptyValue(String...values){
		String value = "";
		
		if(values != null){
			for(String v : values){
				if(StringUtils.isNotEmpty(v)){
					value = v;
					break;
				}
			}
		}
		
		return value;
	}
	
	/**
	 * 随机从source中获得count个元素
	 * @param source 源数组
	 * @param count 元素个数
	 * @return 随机得到的数组列表
	 */
	public static<T> List<T> getRandomElements(List<T> source, int count){
		List<T> target = source;
		
		do{
			if(CollectionUtils.isEmpty(source)) break;
			if(count <= 0 || source.size() <= count){
				target = new ArrayList<>(source);
				Collections.shuffle(target);
				break;
			}
			
			List<T> list = new ArrayList<T>(source);
			target = new ArrayList<T>();
			while(target.size() < count){
				Random feed = new Random();
				int index = feed.nextInt(list.size());
				target.add(list.get(index));
				list.remove(index);
			}
			
		}while(false);
		
		return target;
	}
	
	/**
	 * 按照generator产生的建值对values分组
	 * @param values 要分组的集合
	 * @param generator 键值构造器，用于构造键值
	 * @return 分组结果
	 */
	public static<K, V> Map<K, List<V>> group(Collection<V> values, KeyGenerator<K, V> generator){
		return group(values, generator, null, null);
	}
	
	/**
	 * 按照generator产生的建值对values分组， 使用comparator对键值比较并排序
	 * @param values 要分组的集合
	 * @param generator 键值构造器，用于构造键值
	 * @param comparator 键值比较器
	 * @param sort 排序类型
	 * @return 分组结果
	 */
	public static<K, V> Map<K, List<V>> group(Collection<V> values, KeyGenerator<K, V> generator, final Comparator<K> comparator, Sort sort){
		Map<K, List<V>> groups;
		
		if(comparator != null && sort != null){
			if(Sort.Asc == sort){
				groups = new TreeMap<>(new Comparator<K>(){
					@Override
					public int compare(K k1, K k2) {
						return comparator.compare(k1, k2);
					}
				});
			}else{
				groups = new TreeMap<>(new Comparator<K>(){
					@Override
					public int compare(K k1, K k2) {
						return comparator.compare(k2, k1);
					}
				});
			}
		}else{
			groups = new HashMap<>();
		}
		
		if(CollectionUtils.isNotEmpty(values)){
			for(V v : values){
				K key = generator.getKey(v);
				
				List<V> elements = groups.get(key);
				if(elements == null){
					elements = new ArrayList<>();
					groups.put(key, elements);
				}
				
				elements.add(v);
			}
		}
		
		return groups;
	}
	
	/**
	 * 比较两个数组中元素是否都相等，如果数组长度不同，认为两个数组不等
	 * @param src 源数组
	 * @param dest 目标数组
	 * @return 0相等，否则不相等
	 */
	public static<T> int compare(List<T> src, List<T> dest){
		int diff = getSize(src) - getSize(dest);

		if(diff == 0 && src != null && dest != null){
			for(int i = 0; i < src.size(); i++){
				if(!src.get(i).equals(dest.get(i))){
					diff = 1;
					break;
				}
			}
		}
		
		return diff;
	}
	
	/**
	 * 按照分隔符分割字符串，并去除重复的元素
	 * @param text 要分割的字符串
	 * @param delimiter 分隔符
	 * @return 分割后结果
	 */
	public static List<String> splitDistinct(String text, String delimiter){
		return StringUtils.isNotBlank(text) ? new ArrayList<String>(new HashSet<>(Arrays.asList(StringUtils.split(text, delimiter)))) : new ArrayList<String>();
	}

	/**
	 * 按照分隔符分割字符串，并去除重复的元素和空格
	 * @param text 要分割的字符串
	 * @param delimiter 分隔符
	 * @return 分割后结果
	 */
	public static List<String> splitTrimDistinct(String text, String delimiter){
		if(StringUtils.isBlank(text)){
			return new ArrayList<>();
		}
		
		List<String> list = new ArrayList<>(new HashSet<>(Arrays.asList(StringUtils.split(StringUtils.trimToEmpty(text), delimiter))));
		List<String> results = new ArrayList<>();
		for(String s : list){
			results.add(StringUtils.trimToEmpty(s));
		}
		return results;
	}
	
	/**
	 * 按照分隔符分割字符串，去除重复的元素和空格并排序
	 * @param text 要分割的字符串
	 * @param delimiter 分隔符
	 * @param sort 排序类型
	 * @return 分割后结果
	 */
	public static List<String> splitTrimDistinct(String text, String delimiter, final Sort sort){
		return splitTrimDistinct(text, delimiter, StringConstructor.instance, sort);
	}
	
	/**
	 * 按照分隔符分割字符串，去除重复的元素并转换类型
	 * @param text 要分割的字符串
	 * @param delimiter 分隔符
	 * @param constructor 类型构造器
	 * @return 分割后结果
	 */
	public static<T> List<T> splitTrimDistinct(String text, String delimiter, Constructor<T> constructor){
		return splitTrimDistinct(text, delimiter, constructor, null);
	}
	
	/**
	 * 按照分隔符分割字符串，去除重复的元素，排序并转换类型
	 * @param text 要分割的字符串
	 * @param delimiter 分隔符
	 * @param constructor 类型构造器
	 * @param sort 排序类型
	 * @return 分割后结果
	 */
	public static<T> List<T> splitTrimDistinct(String text, String delimiter, Constructor<T> constructor, final Sort sort){
		List<T> list = new ArrayList<>();
		
		if(StringUtils.isBlank(text)){
			return list;
		}
		String target = text.replaceAll("\\s", "");
		
		Set<String> set;
		
		if(sort != null){
			set = new TreeSet<>(new Comparator<String>(){
				@Override
				public int compare(String s1, String s2) {
					int delt = 0;
					
					if(sort == Sort.Asc){
						delt = s1.compareTo(s2);
					}else{
						delt = s2.compareTo(s1);
					}
					
					return delt;
				}
			});
		}else{
			set = new HashSet<>();
		}
		
		set.addAll(Arrays.asList(StringUtils.split(target, delimiter)));
		
		
		for(String s : set){
			list.add(constructor.construct(s));
		}
		
		return list;
	}
	
	/**
	 * 获得列表元素所有组合，如abc的组合可以是
	 * <ul>
	 * <li>a</li>
	 * <li>b</li>
	 * <li>c</li>
	 * <li>a,b</li>
	 * <li>a,c</li>
	 * <li>b,c</li>
	 * <li>a,b,c</li>
	 * </ul>
	 * @param data 包含目标组合元素的列表
	 * @return 组合结果
	 */
	public static<T> List<List<T>> getAllCombination(Collection<T> data){
		List<List<T>> list = new ArrayList<>();
		
		if(CollectionUtils.isNotEmpty(data)){
			int i = 0;
			
			for(T t : data){
				List<T> combines = new ArrayList<>();
				combines.add(t);
				
				List<T> remains = new ArrayList<>(data);
				remains = remains.subList(++i, data.size());
				
				List<List<T>> otherCombines = getAllCombination(remains);
				
				list.add(combines);
				for(List<T> l : otherCombines){
					List<T> c = new ArrayList<>();
					c.add(t);
					c.addAll(l);
					list.add(c);
				}
			}
		}
		
		return list;
	}
	
	/**
	 * 将对象转化为指定分隔符分隔的字符串
	 * @param source		目标对象
	 * @param delimiter	分隔符
	 * @param picker	字符串提取器，用于从对象中提取字符串
	 * @return	以指定分隔符分隔的字符串
	 */
	public static<T> String join(List<T> source, String delimiter, StringValuePicker<T> picker){
		String text = "";
		
		if(CollectionUtils.isNotEmpty(source)){
			List<String> values = new ArrayList<>();
			
			for(T t : source){
				values.add(picker.getValue(t));
			}
			
			text = StringUtils.join(values, delimiter);
		}
		
		return text;
	}
	
	/**
	 * 将对象转化为数组
	 * @param source	目标对象
	 * @param picker	对象提取器
	 * @return	对象转化的数组
	 */
	public static<T, V> List<V> toList(List<T> source, ValuePicker<T, V> picker){
		List<V> list = new ArrayList<>();
		
		if(CollectionUtils.isNotEmpty(source)){
			for(T t : source){
				list.add(picker.getValue(t));
			}
		}
		
		return list;
	}
	
	private DataUtils(){}
}
